#include <stdio.h>
#include <string.h>
#include <mqueue.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

// 缓冲区
static char send_str[1024];
static char read_str[1024];
// 生明队列路径
static char *my_mq_name;
// 声明队列标识符
static mqd_t my_queue;
static mqd_t he_queue;

void * read_callback(void *argv)
{
    //读取数据
    char *str = argv;
    while(1)
    {
        //清除里面可能残留的信息
        memset(read_str,0,strlen(read_str));
        //读队列
        ssize_t result =  mq_receive(he_queue,read_str,1024,0);
        //判断是否成功
        if(result <  0)
        {
            //printf("cao\n");
            //跳过本次循环
            continue;
        }
        //到这里成功
        printf("%s:%s\n",str,read_str);
    }
}

void signal_callback(int sig)
{
    //清除队列
    mq_unlink(my_mq_name);
    //释放内存
    free(my_mq_name);
    exit(EXIT_SUCCESS);
}

int main(int argc, char const *argv[])
{
    //注册结束信号
    signal(SIGINT,signal_callback);
    // 判断参数是否正确
    if (argc != 3)
    {
        printf("参数不足 需要三个参数...\n");
        exit(EXIT_FAILURE);
    }

    // 暂时先把数据写到写缓存区
    sprintf(send_str, "/%s", argv[1]);
    // 用一个变量来保存队列路径
    my_mq_name = malloc(strlen(send_str) + 1);
    // 创建本地队列
    struct mq_attr attr;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = 1024;
    my_queue = mq_open(send_str, O_RDWR | O_CREAT, 0644, &attr);
    // 判断是否创建成功
    if (my_queue == -1)
    {
        perror("my create");
        exit(EXIT_FAILURE);
    }

    // 创始打开对方队列  对多尝试10次
    int cont = 10;
    sprintf(read_str, "/%s", argv[2]);
    while (cont--)
    {
        he_queue = mq_open(read_str, O_RDWR);
        // 判断是否开启成功
        if (he_queue != -1)
        {
            // 成功
            break;
        }
        perror("he pueue");
        sleep(1);
    }

    // 判断是否茶超出限制
    if (cont <= 0)
    {
        printf("打开对方队列失败...");
        // 删除本地队列
        mq_unlink(my_mq_name);
        free(my_mq_name);
        exit(EXIT_FAILURE);
    }

    // 创建子线程  主线程负责向自己队列里面写   子线程负责在对面队列读
    pthread_t thread;
    pthread_create(&thread, NULL, read_callback, (void *)argv[2]);

    // 写数据队列
    while (1)
    {
        //清除可能残留数据
        memset(send_str,0,strlen(send_str));
        // 对终端世界
        scanf("%s", send_str);
        printf("%s = %s\n",argv[1],send_str);
        mq_send(my_queue, send_str, 1024, 0);
    }

    return 0;
}
